﻿using Common;
using Device;
using LiveCharts;
using Microsoft.Win32;
using OfficeOpenXml;
using FCTIP20.Procdure;
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Collections.Generic;
using static OfficeOpenXml.ExcelErrorValue;
using NewDevice;
using NewDevice.RS485;

namespace FCTIP20.ViewModel
{
    public class PrintTemplate
    {
        public string Number { get; set; }
        public string Value { get; set; }
    }

    internal partial class MainWindowModel : NotifyBase
    {
        #region IO监控

        public ObservableCollection<bool> DOStatus1 { get; set; }

        public ObservableCollection<bool> DIStatus1 { get; set; }

        #endregion IO监控

        #region other

        private int logIndex = 1;
        public int SelectedItemValue { get; set; }

        /// <summary>
        /// 系统状态
        /// </summary>
        public MachineStatus MachineStatus { get; set; }

        public Config Config { get; set; }

        public class Chart
        {
            public int Value { get; set; }
        }

        public Func<ChartPoint, string> PointLabel { get; set; }
        public ObservableCollection<Chart> ChartData { get; set; }
        private DateTime _selectDate;

        public DateTime SelectDate
        {
            get
            {
                return _selectDate;
            }
            set
            {
                _selectDate = value;
                this.DoNotify();
            }
        }

        private List<PrintTemplate> _items;

        public List<PrintTemplate> Items
        {
            get
            {
                return _items;
            }
            set
            {
                _items = value;
                this.DoNotify();
            }
        }

        public PrintTemplate PrintMobanItems { get; set; }
        private CancellationTokenSource cancellationTokenSource;
        private string _log;

        public string Log
        {
            get { return _log; }
            set
            {
                Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    _log = $"[{logIndex++.ToString()}] {value}";
                    this.DoNotify();
                }));
            }
        }

        private bool? _testResult;

        public bool? TestResult
        {
            get { return _testResult; }
            set
            {
                _testResult = value;
                this.DoNotify();
            }
        }

        private int _okCount;

        public int OkCount
        {
            get { return _okCount; }
            set
            {
                _okCount = value;
                this.DoNotify();
                if (Config != null)
                {
                    Config.OkCount = value;
                    ConfigHelper.SaveConfig(Config, configName);
                }
            }
        }

        private int _ngCount;

        public int NgCount
        {
            get { return _ngCount; }
            set
            {
                _ngCount = value;
                this.DoNotify();
                if (Config != null)
                {
                    Config.NgCount = value;
                    ConfigHelper.SaveConfig(Config, configName);
                }
            }
        }

        #endregion other

        #region command

        public CommandBase PassNgCountClearCommand { get; set; }
        public CommandBase ResetCommand { get; set; }
        public CommandBase StartCommand { get; set; }
        public CommandBase SaveConfigCommand { get; set; }
        public CommandBase SaveDataCommand { get; set; }
        public CommandBase RadioButtonCommand { get; set; }

        private void PassNgCountClear(object obj)
        {
            NgCount = 0;
            OkCount = 0;
        }

        private void StartEvent(object obj)
        {
            Task.Run(() =>
            {
                try
                {
                    isEmpStop = false;
                    // 0 系统状态判定
                    switch (MachineStatus)
                    {
                        case MachineStatus.Running:
                            Log = "设备运行中";

                            return;

                        case MachineStatus.Stop:
                            Log = "设备处于停止状态";
                            return;

                        default:
                            break;
                    }
                    TextList = new ObservableCollection<ListViewDataArr>();
                    MachineStatus = MachineStatus.Used;
                    if (this.PrintMobanItems == null)
                    {
                        MachineStatus = MachineStatus.Idle;
                        MessageBox.Show("请选择打印模板");
                        AddData(false, "请选择打印模板");
                        return;
                    }
                    //链接镭雕机
                    bool SP = StartPrint();
                    if (!SP)
                    {
                        AddData(false, "连接镭雕机失败");
                        return;
                    }
                    Global.IsBusy = true;
                    bool AutoChannel = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.Auto);
                    string PrintMobanName = this.PrintMobanItems.Value;

                    //开始打印
                    StartContent(PrintMobanName);
                }
                catch (Exception ex)
                {
                    Mylog.Error(ex, ex.Message);
                    Log = ex.Message;
                    AddData(false, ex.Message);
                    EmStop();
                }
                finally
                {
                    // EmStop();
                    Global.IsBusy = false;
                }
            });
        }

        private void ResetEvent(object obj)
        {
            Task.Run(() =>
            {
                try
                {
                    isEmpStop = false;
                    switch (MachineStatus)
                    {
                        case MachineStatus.Running:
                            Log = "设备运行中，禁止复位";
                            AddData(false, "设备运行中，禁止复位");
                            return;

                        default:
                            break;
                    }

                    if (Global.IsBusy)
                    {
                        Log = "正在进行其它操作，请完成后再试！";
                        AddData(false, "正在进行其它操作，请完成后再试");
                        return;
                    }
                    Global.IsBusy = true;
                    //if (!StartPrint())
                    //{
                    //    return;
                    //}
                    Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOAriWorkC, false);
                    Wait(50);
                    Global.PQW_IO.OffAll(1);//关闭所有IO
                    Wait(1000);
                    MachineStatus = MachineStatus.Idle;
                    Reset_FG();
                    Log = "复位完成";
                }
                catch (Exception ex)
                {
                    Log = ex.Message + "!";
                    AddData(false, ex.Message);
                    EmStop();
                }
            });
        }

        #endregion command

        #region ctor

        private string configName = "config.xml";
        private bool refresh = false;

        public MainWindowModel()
        {
            try
            {
                Config = ConfigHelper.Load(configName);
                OkCount = Config.OkCount;
                NgCount = Config.NgCount;
                TestResult = true;
                SelectDate = DateTime.Now;
                PassNgCountClearCommand = new CommandBase(PassNgCountClear);
                StartCommand = new CommandBase(StartEvent);
                ResetCommand = new CommandBase(ResetEvent);
                SaveDataCommand = new CommandBase(SaveData);
                IODevice();
                Wait(1000);
                Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOAriWorkC, false);
                Wait(50);
                Global.PQW_IO.OffAll(1);//关闭所有IO
                Wait(1000);
                DOStatus1 = new ObservableCollection<bool>();
                DIStatus1 = new ObservableCollection<bool>();
                refresh = true;
                for (int i = 0; i < 16; i++)
                {
                    DOStatus1.Add(false);
                    DIStatus1.Add(false);
                }
                refresh = false;
                DOStatus1.CollectionChanged += DOStatus_CollectionChanged1;
                DIStatus1.CollectionChanged += DIStatus_CollectionChanged1;
                TextList = new ObservableCollection<ListViewDataArr>();
                //自动采集
                AutoChannel();
                Thread.Sleep(1000);
                ////初始化打印模板选取
                CreatePrintCombox();
                PointLabel = chartPoint => string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);
                NewContentView();
                //分割器复位
                Reset_FG();
                MachineStatus = MachineStatus.Idle;
                Thread.Sleep(1000);
                Log = "初始化完成";
            }
            catch (Exception e)
            {
                Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOAriWorkC, false);
                Wait(50);
                Global.PQW_IO.OffAll(1);//关闭所有IO
                Global.PQW_IO.SetDO(1, (int)DODefine.RedLight, true);
                Log = e.Message + "!";
            }
        }

        //复位分割器
        public void Reset_FG()
        {
            bool RevolveBase = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.RevolveBase);//// 旋转气缸原点
            bool RevolveBase1 = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.RevolveBase1);//旋转气缸原点1
            bool AriWorkBase = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.AriWorkBase);// 插线气缸原点
            if (RevolveBase == true && RevolveBase1 == true && AriWorkBase == true)
            {
                Global.BreakD = true;
                Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOBreakUp, true);//分割器动作
                Log = "分割器动作";
                Thread.Sleep(1000);
                while (true)
                {
                    //bool BreakUp = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.BreakUp);//分割器是否到位
                    if (Global.BreakUpStats)
                    {
                        Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOBreakUp, false);//分割器停止
                        Log = "分割器到位停止";
                        Global.BreakUpStats = false;
                        Global.BreakD = false;
                        Global.IsBusy = false;
                        Global.BreakUpStatsNum = 0;
                        break;
                    }
                    if (MachineStatus == MachineStatus.Stop)
                    {
                        EmStop();
                        break;
                    }
                    Thread.Sleep(300);
                }
                MachineStatus = MachineStatus.Idle;
            }
            else
            {
                Log = "复位失败!";
            }
        }

        private void AutoChannel()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        refresh = true;
                        Global.PQW_IO.GetDO((int)DOslaveID.slaveID);//缓存所有通道状态，不然GETDO(INT ,INT)报错
                                                                    // Global.PQW_IO.GetDI((int)DOslaveID.slaveID);
                        for (int i = 0; i < 16; i++)
                        {
                            DOStatus1[i] = Global.PQW_IO.GetDO((int)DOslaveID.slaveID, i);
                            //  DIStatus1[i] = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, i);
                        }
                        refresh = false;
                        Thread.Sleep(800);
                    }
                    catch (Exception ex)
                    {
                        Log = ex.Message;
                    }
                }
            });
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        //refresh = true;
                        // Global.PQW_IO.GetDO((int)DOslaveID.slaveID);//缓存所有通道状态，不然GETDO(INT ,INT)报错
                        Global.PQW_IO.GetDI((int)DOslaveID.slaveID);
                        for (int i = 0; i < 16; i++)
                        {
                            //DOStatus1[i] = Global.PQW_IO.GetDO((int)DOslaveID.slaveID, i);
                            DIStatus1[i] = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, i);
                        }
                        //refresh = false;
                        Thread.Sleep(50);
                    }
                    catch (Exception ex)
                    {
                        Log = ex.Message;
                    }
                }
            });
        }

        private void IODevice()
        {
            try
            {
                SerialBase serial = new SerialBase("FCTIP20");
                serial.Connect(Config.IOModule1, 9600);
                PQW_IO pqw = new PQW_IO(serial);
                pqw.DICount = 16;
                pqw.DOCount = 16;
                Global.PQW_IO = pqw;
                Global.PQW_IO.GetDO((int)DOslaveID.slaveID);//缓存所有通道状态，不然GETDO(INT ,INT)报错
                bool isOnline = pqw.IsDeviceOnline();
                if (!isOnline)
                {
                    Log = $"IO模块不在线,地址[{DOslaveID.slaveID}]";
                }
            }
            catch (Exception ex)
            {
                Log = $"IO模块不在线,地址[{DOslaveID.slaveID}]";
            }
        }

        private void CreatePrintCombox()
        {
            try
            {
                var PRINT = Config.ListConfigs;
                Items = new List<PrintTemplate>();
                foreach (var config in PRINT)
                {
                    Items.Add(new PrintTemplate { Value = config.MoBanName });
                }
            }
            catch (Exception ex)
            {
                Log = ex.ToString();
            }
        }

        private PQW_IO pqw = null;
        private bool isEmpStop = false;

        private void DIStatus_CollectionChanged1(object sender, NotifyCollectionChangedEventArgs e)
        {
            int channelValue = (int)e.NewStartingIndex;
            var tempStart = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.Start);
            var tempEmgStop = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.EmgStop);//急停
            var GGStop = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.OpenDoor); //安全门
            bool redLightStatus = Global.PQW_IO.GetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight);
            bool BreakUpStatus = Global.PQW_IO.GetDI((int)DOslaveID.slaveID, (int)DIDefine.BreakUp);//分割器是否到位

            if (Global.BreakD == true)//分割器是否动作
            {
                if (!BreakUpStatus)//动作中检测到位信号
                {
                    Global.BreakUpStatsNum = 1;//到位信号灭过次数
                }
                if (Global.BreakUpStatsNum >= 1)
                {
                    if (BreakUpStatus)//检测到位信号
                    {
                        Global.BreakUpStats = true;
                        Global.BreakD = false;
                        Global.BreakUpStatsNum = 0;
                    }
                }
            }
            if (tempStart)
            {
                if (MachineStatus != MachineStatus.Running && MachineStatus != MachineStatus.Used)
                {
                    MachineStatus = MachineStatus.Used;
                    //开始
                    StartAction();
                }
                else
                {
                }

                //MachineStatus = MachineStatus.Running;
            }
            if (!tempEmgStop)
            {
                if (redLightStatus == false && channelValue == 1)
                {
                    if (!isEmpStop)
                    {
                        isEmpStop = true;

                        Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOAriWorkC, false);
                        Thread.Sleep(50);
                        Global.PQW_IO.OffAll(1);
                        Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight, true);
                        Thread.Sleep(500);
                        Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight, false);
                        stopMark();
                        Global.IsBusy = false;
                        MachineStatus = MachineStatus.Stop;
                        Log = "设备急停!";
                    }
                }
                //EmgStopAction();
            }
            else
            {
                isEmpStop = false;
            }

            if (!GGStop)
            {
                UsedAction();
                if (!Global.PQW_IO.GetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight) && channelValue == 1)
                {
                    Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.DOAriWorkC, false);
                    Thread.Sleep(50);
                    Global.PQW_IO.OffAll(1);
                    Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight, true);
                    Thread.Sleep(500);
                    Global.PQW_IO.SetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight, false);
                    Global.IsBusy = false;
                    MachineStatus = MachineStatus.Stop;
                    Log = "开门急停!";
                }
            }
            if (MachineStatus == MachineStatus.Stop)
            {
                if (!Global.PQW_IO.GetDO((int)DOslaveID.slaveID, (int)DODefine.RedLight) && channelValue == 1)
                {
                    Global.IsBusy = false;
                    EmgStopAction();
                }
            }
        }

        private void DOStatus_CollectionChanged1(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (!refresh)
            {
                int index = e.NewStartingIndex;
                bool value = (sender as ObservableCollection<bool>)[index] ? true : false;
                Global.PQW_IO.SetDO((int)DOslaveID.slaveID, index, value);
            }
        }

        private object _contentChecked;

        public object ContentChecked
        {
            get { return _contentChecked; }
            set
            {
                _contentChecked = value;
                this.DoNotify();
            }
        }

        private BitmapImage currentImage; // 当前显示的图片

        public BitmapImage CurrentImage
        {
            get { return currentImage; }
            set
            {
                currentImage = value;
                this.DoNotify();
            }
        }

        private void ShowImage(string imagePaths)
        {
            // 创建 BitmapImage 对象并设置图片路径
            BitmapImage bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.UriSource = new Uri(imagePaths, System.UriKind.RelativeOrAbsolute);
            bitmap.EndInit();

            // 设置当前显示的图片
            CurrentImage = bitmap;
        }

        private string _userControlChecked;

        private void SaveData(object obj)
        {
            //"2023/12/1 0:00:00"
            string selectDate = SelectDate.ToString("yyyyMMdd");
            string dir = "";
            switch (_userControlChecked)
            {
                case "rbMainControl":
                    dir = @$"{Environment.CurrentDirectory}\\Data\\MainControl\\{selectDate}";
                    break;

                default:
                    break;
            }
            if (Directory.Exists(dir))
            {
                string[] fileNames = Directory.GetFiles(dir);

                // 创建一个 SaveFileDialog 实例
                SaveFileDialog saveFileDialog = new SaveFileDialog();

                // 设置对话框的标题
                saveFileDialog.Title = "保存 Excel 文件";

                // 设置文件类型筛选
                saveFileDialog.Filter = "Excel 文件|*.xlsx";

                // 显示对话框并检查用户是否点击了 "保存" 按钮
                if (saveFileDialog.ShowDialog() == true)
                {
                    // 用户选择的文件路径
                    string filePath = saveFileDialog.FileName;
                    ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                    using (var package = new ExcelPackage())
                    {
                        bool isSaveedOk = false;
                        var worksheet = package.Workbook.Worksheets.Add("Sheet1");

                        worksheet.Cells["A1"].Value = "SN";
                        worksheet.Cells["B1"].Value = "时间";
                        worksheet.Cells["C1"].Value = "结果";

                        for (int i = 0; i < fileNames.Length; i++)
                        {
                            int index = Path.GetFileName(fileNames[i]).IndexOf(selectDate);
                            string fileName = Path.GetFileName(fileNames[i]);
                            if (fileName.Contains("~"))
                            {
                                continue;
                            }
                            string SN = fileName.Substring(0, index - 1);
                            string dateTime = fileName.Substring(index, 14);
                            string result = fileName.Substring((index + 15));

                            worksheet.Cells[$"A{i + 2}"].Value = SN;
                            worksheet.Cells[$"B{i + 2}"].Value = dateTime;
                            worksheet.Cells[$"C{i + 2}"].Value = result.Contains("PASS") ? "PASS" : "FAILED";
                        }
                        try
                        {
                            package.SaveAs(new FileInfo(filePath));
                            isSaveedOk = true;
                        }
                        catch (Exception)
                        {
                            Log = "文件已打开,请关闭并重试!";
                        }
                        if (isSaveedOk)
                        {
                            Log = "保存成功";
                        }
                    }
                }
            }
            else
            {
                Log = "选择时间内无数据!";
            }
        }

        private void StartAction()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                StartEvent(null);
            });
        }

        private void EmgStopAction()
        {
            switch (MachineStatus)
            {
                case MachineStatus.Running:
                    MachineStatus = MachineStatus.Stop;

                    break;

                case MachineStatus.Stop:
                    MachineStatus = MachineStatus.Stop;
                    break;

                default:
                    break;
            }
        }

        private void UsedAction()
        {
            switch (MachineStatus)
            {
                case MachineStatus.Running:
                    MachineStatus = MachineStatus.Stop;
                    break;

                case MachineStatus.Stop:
                    break;

                case MachineStatus.Idle:
                    break;

                default:
                    break;
            }
        }

        #endregion ctor
    }
}